﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using ComClassLibrary;
using KeyboardArg;

namespace SoftKeyBoard
{
    public partial class FormKeyInputing : Form
    {
        private KeyBoardArgs _keyboardArg = new KeyBoardArgs();

        public KeyBoardArgs KeyboardArgs
        {
            get { return _keyboardArg; }
        }

        public const int USER_MESSAGE_OK = 0x0405;//用户自定义消息的开始数值
        
        public const int USER_MESSAGE_CLEAR = 0x0406;//用户自定义消息的开始数值
     
        private LetterKeyBoard keyboard;

        private bool _isPuttingPwd = false;

        public bool IsPuttingPwd
        {
            set
            {
                _isPuttingPwd = true;
            }
            get
            {
                return _isPuttingPwd;
            }
        }

        public string InputString
        {
            private set;
            get;
        }
        
        private string _title = "";

        public FormKeyInputing()
        {
            InitializeComponent();
        }

        public FormKeyInputing(KeyBoardArgs KeyBoardArgs)
                  : this()
        {
            SetInputToolArg(KeyBoardArgs);
        }

        /// <summary>
        /// 窗口隐藏事件
        /// </summary>
        public event EventHandler Hidden;
        protected void OnWndHidden()
        {
            if (Hidden != null)
            {
                Hidden(this, new EventArgs());
            }
        }

        public void SetLocation(Rectangle rect)
        {
            // 计算窗体在屏幕上的位置，使其位于屏幕中心
            int x = rect.Left + (rect.Width - Width) / 2;
            int y = rect.Top + (rect.Height - Height) / 2;

            // 设置窗体的位置
            Location = new Point(x, y);
        }

        public void SetInputToolArg(KeyBoardArgs args)
        {
            if (args == null)
            {
                return;
            }
            _keyboardArg = args;
            _title = _keyboardArg.Title;
            textBoxContent.MaxLength = _keyboardArg.MaxLength;
            textBoxContent.Text = _keyboardArg.Content;
            int CurrStation = textBoxContent.SelectionStart;
            if (CurrStation <= 0 && !string.IsNullOrEmpty(textBoxContent.Text))
            {
                textBoxContent.SelectionStart = textBoxContent.Text.Length;
            }
            textBoxContent.Focus();
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            InputString = "";
            if (_keyboardArg == null || _keyboardArg.MsgReceiver == IntPtr.Zero)
            {
                this.DialogResult = DialogResult.Cancel;
                this.Close();
                return;
            }
            _keyboardArg.Content = "";
            _keyboardArg.Command = "Cancel";
            _keyboardArg.PassageType = SendMessageType.Response;
            int uMsg = (int)MessageType.WM_COPYDATA;
            string strMsgText = JsonHandler.ConvertToJsonString(_keyboardArg);
            byte[] data = System.Text.Encoding.UTF8.GetBytes(strMsgText);
            COPYDATASTRUCT_INTPTR cds = new COPYDATASTRUCT_INTPTR();
            cds.dwData = (IntPtr)uMsg;
            cds.cbData = data.Length;
            cds.lpData = Marshal.AllocHGlobal(data.Length);
            Marshal.Copy(data, 0, cds.lpData, data.Length);
            ComClassLibrary.Message.SendMessage(_keyboardArg.MsgReceiver, uMsg, 0, ref cds);
            cds.Free();
            this.DialogResult = DialogResult.Cancel;
            this.Hide();
            OnWndHidden();
        }

        private void btnOK_Click(object sender, EventArgs e)
        {         
            if (!Check())
            {
                return;
            }
            InputString = textBoxContent.Text.Trim();
            _keyboardArg.PassageType = SendMessageType.Response;
            _keyboardArg.Content = InputString;
            _keyboardArg.Command = "OK";
            if (_keyboardArg == null || _keyboardArg.MsgReceiver == IntPtr.Zero)
            {
                this.DialogResult = DialogResult.OK;
                this.Close();
                return;
            }
            SendMessage();
            this.DialogResult = DialogResult.OK;
            this.Hide();
            OnWndHidden();
        }

        private void FormKeyInputing_Load(object sender, EventArgs e)
        {
            if (_isPuttingPwd)
            {
                textBoxContent.PasswordChar = '*';
            }
            else
            {
                textBoxContent.PasswordChar = (char)0;
            }
            labelTitle.Text = _title;
            keyboard = new LetterKeyBoard(this.Handle);
            keyboard.Dock = DockStyle.Fill;
            keyboard.TopLevel = false;
            this.panel1.Controls.Clear();
            this.panel1.Controls.Add(keyboard);
            keyboard.KeyClick += OnKeyClick;
            keyboard.BackspaceKeyClick += OnBackspaceClick;
            keyboard.Show();
            textBoxContent.Focus();
        }

        /// <summary>
        /// 键盘点击事件
        /// </summary>
        /// <param name="e"></param>
        private void OnKeyClick(object sender, CharClickEventArgs e)
        {
            textBoxContent.AppendText(e.Char);
        }

        /// <summary>
        /// 点击退格事件
        /// </summary>
        /// <param name="e"></param>
        private void OnBackspaceClick(object sender, EventArgs e)
        {
            if (textBoxContent.TextLength > 0)
            {
                textBoxContent.Text = textBoxContent.Text.Substring(0, textBoxContent.TextLength - 1);
            }
        }

        private void OnClear()
        {
            textBoxContent.Clear();
            textBoxContent.Focus();
        }

        public bool Check()
        {        
            if (string.IsNullOrEmpty(textBoxContent.Text))
            {
                MessageBox.Show(this,
                   "输入不能为空!请重新输入...",
                   "错误提示",
                   MessageBoxButtons.OK,
                   MessageBoxIcon.Error);
                return false;
            }          
            return true;
        }

        public void OnbuttonOK_Click(ref System.Windows.Forms.Message m)
        {
            if (Check())
            {
                m.Result = (IntPtr)0x00;
                InputString = textBoxContent.Text.Trim();
                _keyboardArg.PassageType = SendMessageType.Response;
                _keyboardArg.Content = InputString;
                _keyboardArg.Command = "OK";
                if (_keyboardArg == null || _keyboardArg.MsgReceiver == IntPtr.Zero)
                {
                    this.DialogResult = DialogResult.OK;
                    this.Close();
                    return;
                }
                SendMessage();
                this.DialogResult = DialogResult.OK;
                this.Hide();
                OnWndHidden();
            }
            else
            {
                m.Result = (IntPtr)0xff;
                MessageBox.Show(this,
                    "信息输入有误!请重新输入...",
                    "输入有误",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
                textBoxContent.Focus();
            }
        }

        private bool SendMessage()
        {
            if (_keyboardArg.MsgReceiver == IntPtr.Zero)
            {
                MessageBox.Show("句柄错误", "句柄错误", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return false;
            }
            int uMsg = (int)MessageType.WM_COPYDATA;
            string strMsgText = JsonHandler.ConvertToJsonString(_keyboardArg);
            byte[] data = System.Text.Encoding.UTF8.GetBytes(strMsgText);
            COPYDATASTRUCT_INTPTR cds = new COPYDATASTRUCT_INTPTR();
            cds.dwData = (IntPtr)uMsg;
            cds.cbData = data.Length;
            cds.lpData = Marshal.AllocHGlobal(data.Length);
            Marshal.Copy(data, 0, cds.lpData, data.Length);
            ComClassLibrary.Message.SendMessage(_keyboardArg.MsgReceiver, uMsg, 0, ref cds);
            cds.Free();
            return true;
        }


        protected override void DefWndProc(ref System.Windows.Forms.Message m)
        {
            switch (m.Msg)
            {
                case USER_MESSAGE_OK:
                    OnbuttonOK_Click(ref m);
                    break;
                case USER_MESSAGE_CLEAR:
                    OnClear();
                    break;
                default:
                    base.DefWndProc(ref m);
                    break;
            }
        }

        private void FormKeyInputing_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (keyboard != null && keyboard.IsHandleCreated)
            {
                keyboard.Close();
            }
        }

        private bool IsInMovingArea(Point p)
        {
            if (p.X > labelTitle.Left && p.Y < textBoxContent.Top)
            {
                return true;
            }
            return false;
        }

        private Point _mousePoint;

        private void FormKeyInputing_MouseMove(object sender, MouseEventArgs e)
        {
            if (!IsInMovingArea(e.Location))
            {
                return;
            }
            if (e.Button == MouseButtons.Left)
            {
                int X = MousePosition.X - _mousePoint.X;
                int Y = MousePosition.Y - _mousePoint.Y;
                this.Location = new Point(X, Y);
            }         
        }

        private void FormKeyInputing_MouseDown(object sender, MouseEventArgs e)
        {
            if (!IsInMovingArea(e.Location))
            {
                return;
            }
            if (e.Button == MouseButtons.Left)
            {
                _mousePoint.X = e.X;
                _mousePoint.Y = e.Y;
            }
        }
    }
}
